#ifndef BASE_CTTIME_H_
#define BASE_CTTIME_H_

#include <sys/time.h>
#include <time.h>
#include <string>
#include <vector>

//real time class
//encapsulation struct timeval
class ctRTime
{
        private:

                unsigned long msecs_;

                //get currernt time by msecond
                unsigned long _now()
                {
                        unsigned long retval = 0LL;
                        struct timeval tv;
                        gettimeofday(&tv,NULL);
                        retval = tv.tv_sec;
                        retval *= 1000;
                        retval += tv.tv_usec / 1000;
                        return retval;
                }

                void nowByDelay(int delay)
                {
                        msecs_ = _now();
                        addDelay(delay);
                }

        public:
                ctRTime(const int delay = 0)
                {
                        nowByDelay(delay);
                }

                ctRTime(const ctRTime &rt)
                {
                        msecs_ = rt.msecs_;
                }

                void now()
                {
                        msecs_ = _now();
                }

                unsigned int sec() const
                {
                        return msecs_ / 1000;
                }

                unsigned int msec() const
                {
                        return msecs_ % 1000;
                }

                unsigned long msecs() const
                {
                        return msecs_;
                }

                void setmsecs(unsigned long data)
                {
                        msecs_ = data;
                }

                void addDelay(int delay)
                {
                        msecs_ += delay;
                }

                ctRTime & operator= (const ctRTime &rt)
                {
                        msecs_ = rt.msecs_;
                        return *this;
                }

                const ctRTime & operator+ (const ctRTime &rt)
                {
                        msecs_ += rt.msecs_;
                        return *this;
                }

                const ctRTime & operator- (const ctRTime &rt)
                {
                        msecs_ -= rt.msecs_;
                        return *this;
                }

                bool operator > (const ctRTime &rt) const
                {
                        return msecs_ > rt.msecs_;
                }

                bool operator >= (const ctRTime &rt) const
                {
                        return msecs_ >= rt.msecs_;
                }

                bool operator < (const ctRTime &rt) const
                {
                        return msecs_ < rt.msecs_;
                }

                bool operator <= (const ctRTime &rt) const
                {
                        return msecs_ <= rt.msecs_;
                }

                bool operator == (const ctRTime &rt) const
                {
                        return msecs_ == rt.msecs_;
                }

                unsigned long elapse(const ctRTime &rt) const
                {
                        if (rt.msecs_ > msecs_)
                                return (rt.msecs_ - msecs_);
                        else
                                return 0LL;
                }

                static std::string & getLocalTZ(std::string & s);
                static void getLocalTime(struct tm & tv1,time_t timValue)
                {
                        timValue +=8*60*60;
                        tv1 = *gmtime(&timValue);
                }
};

//Time class.
//encapsulation struct tm
class ctTime
{
        public:

                ctTime()
                {
                        time(&secs_);
                        ctRTime::getLocalTime(tv_,secs_);
                }

                ctTime(const ctTime &ct)
                {
                        secs_ = ct.secs_;
                        ctRTime::getLocalTime(tv_,secs_);
                }

                void now()
                {
                        time(&secs_);
                        ctRTime::getLocalTime(tv_,secs_);
                }

                time_t sec() const
                {
                        return secs_;
                }

                ctTime & operator= (const ctTime &rt)
                {
                        secs_ = rt.secs_;
                        return *this;
                }

                const ctTime & operator+ (const ctTime &rt)
                {
                        secs_ += rt.secs_;
                        return *this;
                }

                const ctTime & operator- (const ctTime &rt)
                {
                        secs_ -= rt.secs_;
                        return *this;
                }

                const ctTime & operator-= (const time_t s)
                {
                        secs_ -= s;
                        return *this;
                }

                bool operator > (const ctTime &rt) const
                {
                        return secs_ > rt.secs_;
                }

                bool operator >= (const ctTime &rt) const
                {
                        return secs_ >= rt.secs_;
                }

                bool operator < (const ctTime &rt) const
                {
                        return secs_ < rt.secs_;
                }

                bool operator <= (const ctTime &rt) const
                {
                        return secs_ <= rt.secs_;
                }

                bool operator == (const ctTime &rt) const
                {
                        return secs_ == rt.secs_;
                }

                time_t elapse(const ctTime &rt) const
                {
                        if (rt.secs_ > secs_)
                                return (rt.secs_ - secs_);
                        else
                                return 0;
                }

                time_t elapse() const
                {
                        ctTime rt;
                        return (rt.secs_ - secs_);
                }

                int getSec()	{ return tv_.tm_sec; }
                int getMin()	{ return tv_.tm_min; }
                int getHour()	{ return tv_.tm_hour; }
                int getMDay()	{ return tv_.tm_mday; }
                int getWDay()	{ return tv_.tm_wday; }
                int getMonth()	{ return tv_.tm_mon+1; }
                int getYear()	{ return tv_.tm_year+1900; }  

        private:
                time_t secs_;
                struct tm tv_;
};

class Timer
{
        public:
                Timer(const float how_long,const int delay=0)
                        : long_((int)(how_long*1000)),timer_(delay*1000)
                {

                }
                Timer(const float how_long,const ctRTime cur) 
                        : long_((int)(how_long*1000)),timer_(cur)
                {
                        timer_.addDelay(long_);
                }
                void next(const ctRTime &cur)
                {
                        timer_=cur;
                        timer_.addDelay(long_);
                } 
                bool operator() (const ctRTime& current)
                {
                        if (timer_ <= current) {
                                timer_ = current;
                                timer_.addDelay(long_);
                                return true;
                        }

                        return false;
                }
        private:
                int long_;
                ctRTime timer_;
};
#endif //BASE_CTTIME_H_
